COM Object Reference Counting by Noam Cohen Listing One // code snippet from CUnknown.h from "Inside COM" by Dale Rogerson, // Microsoft Press. // Modified by Noam Cohen. /////////////////////////////////////////////////////////// class CUnknown : public INondelegatingUnknown { public: // Nondelegating IUnknown implementation // ... protected: // ... // helper functions to register the parameters of the caller // of AddRef and Release() void RegisterAddRef(DWORD _ebp); void RegisterRelease(DWORD _ebp); private: // ... // Reference count for this object // helper function. get information on the caller of // the function whose ebp == _ebp HRESULT ParamsOfCaller(IN DWORD _ebp, OUT ULONG &line, OUT char* szSymbolName, IN UINT nSymNameLen, OUT char* szFileName, INT nFileNameLen, OUT ULONG &displacement); }; // CUnknown Listing Two /////////////////////////////////////////////////////////// // Delegating IUnknown // - Delegates to the nondelegating IUnknown, or to the // outer IUnknown if the component is aggregated. #define DECLARE_IUNKNOWN \ virtual HRESULT __stdcall \ QueryInterface(const IID& iid, void** ppv) \ { \ return GetOuterUnknown()->QueryInterface(iid,ppv) ; \ } ; \ virtual ULONG __stdcall AddRef() \ { \ unsigned int _ebp; \ __asm {mov _ebp, ebp} \ RegisterAddRef(_ebp); \ return GetOuterUnknown()->AddRef() ; \ } ; \ virtual ULONG __stdcall Release() \ { \ unsigned int _ebp; \ __asm {mov _ebp, ebp} \ RegisterRelease(_ebp); \ return GetOuterUnknown()->Release() ; \ } ; Listing Three BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD dwReason, void* /*lpReserved*/) { if (dwReason == DLL_PROCESS_ATTACH) { CFactory::s_hModule = hModule ; // even if we fail, business as usual (void)ghSym.LoadSymbols(); } return TRUE; } Listing Four // ObjData contains all the data relevant to one key (the interface pointer) typedef struct { ObjectName objName; ParamList addRefed; ParamList released; } ObjData; // the container of all the associations typedef std::map ObjectsMap; Listing Five /* This interface can be exposed by a COM object that exposes some identifying properties. */ interface INamedObject2 : IUnknown { /*------------------------------------------------------------------ Get a name for this object's clas ( e.g. "TS demuxer" ) Return: null terminated string */ virtual const char* GetClassName() = 0; /*------------------------------------------------------------------- Get the CLASS id of this COM object. It is recommended to return the CLSID used when creating this object Return: S_OK E_NOTIMPL */ virtual HRESULT GetClassId(const GUID &) = 0; /*------------------------------------------------------------------- Get a name for this object ( e.g. "object in server 34" ) Return: null terminated string */ virtual const char* GetObjectName() = 0; /*------------------------------------------------------------------- Get the INSTANCE id of this COM object. Return: S_OK E_NOTIMPL */ virtual HRESULT GetObjectId(const GUID &) = 0; }; // INamedObject2 // helper macro for those lazy people who need minimal functionality #define CLASS_NAME_IMPL(szClassName) \ const char* GetClassName(){return szClassName;} \ HRESULT GetClassId(const GUID &){ return E_NOTIMPL;}\ const char* GetObjectName(){return "";}\ HRESULT GetObjectId(const GUID &){ return E_NOTIMPL;} #endif 3